package com.ydj.framework.module.init;

import com.ydj.framework.module.init.entity.dao.FwInitVersionDao;
import com.ydj.framework.module.init.entity.query.FwInitVersionQuery;
import com.ydj.framework.module.init.entity.FwInitVersion;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;

import javax.validation.constraints.NotNull;

/**
 * @author rick
 */
@Slf4j
public abstract class BaseInit implements ApplicationListener<ApplicationReadyEvent>, Ordered {
    @Autowired
    private FwInitVersionDao fwInitVersionDao;

    protected BaseInit() {}

    @Data
    @AllArgsConstructor
    protected class InitContext {
        /**
         * 启动脚本的名字
         */
        private String name;

        /**
         * 启动脚本当前的版本号
         */
        private int version;
    }

    /**
     * 上下文
     */
    protected abstract InitContext getContext();

    /**
     * 真正做初始化的函数
     */
    protected abstract void doAction() throws Exception ;

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Override
    public void onApplicationEvent(@NotNull ApplicationReadyEvent applicationReadyEvent) {
        String name = this.getClass().getName();
        FwInitVersion initVersion = new FwInitVersionQuery(fwInitVersionDao).name(name).single();
        if (initVersion == null) {
            initVersion = new FwInitVersion()
                                .setName(name)
                                .setVersion(0);
        }

        InitContext context = getContext();
        if (initVersion.getVersion() == null || context.getVersion() > initVersion.getVersion()) {
            long now = System.currentTimeMillis();
            log.info("启动脚本【{}】开始，现在版本是{}, 准备升级到版本号{}", context.getName(), initVersion.getVersion(), context.getVersion());
            try {
                doAction();
                log.info("启动脚本【{}】结束，耗时{}毫秒", context.getName(), (System.currentTimeMillis() - now));
                // 更新版本号
                initVersion.setVersion(context.getVersion());
                fwInitVersionDao.saveOrUpdate(initVersion);
            } catch (Exception e) {
                log.error("启动脚本【{}】失败。", context.getName(), e);
            }
        } else {
            log.info("启动脚本【{}】不需要启动。现在版本是{}，新的版本是{}", context.getName(), initVersion.getVersion(), context.getVersion());
        }
    }
}